package study.springcloud.gateway.filter.global;

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import study.springcloud.gateway.support.utils.RouteUtils;
import study.springcloud.gateway.support.utils.MdcUtils;
import study.springcloud.gateway.support.utils.WebUtils;

/**
 * https://blog.csdn.net/manzhizhen/article/details/115386684
 */
@Slf4j
//@Component
public class WatchdogFilter implements GlobalFilter {


    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //
        String requestId = makeRequestIdIfAbsent(exchange);
        MdcUtils.put(requestId);
        //order >=2 时，会去掉请求前缀
        String path = RouteUtils.getOriginalRequestURI(exchange).getPath();

        //
        Mono<Void> mono;
        try {
            log.info(">>>>>>[filter] try");
            //
            ServerHttpRequest request = WebUtils.getServerHttpRequest(exchange);
            ServerHttpRequest newRequest = request.mutate().header("fffffffffff", "666666").build();
            ServerWebExchange newExchange = exchange.mutate().request(newRequest).build();

            // next filter, chain.filter(exchange)之前的是 "pre" 部分，之后的也就是 then 里边的是 "post" 部分
            mono = chain.filter(newExchange)
                    .then(Mono.fromRunnable(() -> {
                        try {
                            log.info(">>>>>>[then] try");
                            //
                            ServerHttpResponse response = WebUtils.getServerHttpResponse(exchange);
                            response.getHeaders().add("aaaaaaaaaa", "66666666666666");
                        } finally {
                            //log.info(">>>>>>[then] [{}] cost time [{}] ms", path, System.currentTimeMillis() - 0);
                            log.info(">>>>>>[then] finally");
                            MdcUtils.remove();
                        }
                    }));
        } finally {
            log.info(">>>>>>[filter] finally");
        }
        return mono;
    }

    /**
     * 新增request id
     */
    private String makeRequestIdIfAbsent(ServerWebExchange exchange) {
        //acquire
        String requestId = WebUtils.getRequestId(exchange);
        if (StrUtil.isEmpty(requestId)) {
            // request id
            requestId = String.valueOf(System.currentTimeMillis());
            // add to header
            WebUtils.addRequestHeader(exchange, WebUtils.X_REQUEST_ID, requestId);
        }
        return requestId;
    }
}
